package com.sky.aop;

import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.entity.Employee;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

@Component
@Aspect
@Slf4j
public class AutoFillAspect {


    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
    public void pointcut(){}

    @Before("pointcut()")
    public void autoFill(JoinPoint joinPoint) throws Throwable {
        log.info("进入需要公共字段填入的方法");
        //首先获取方法注解中数据库操作的value值
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();//用来获取方法签名的具体实现。
        Method method = signature.getMethod();// Method：用于获取目标方法和其注解的详细信息。
        AutoFill annotation = method.getAnnotation(AutoFill.class);//获取方法的注解
        //获取填充字段的值
        LocalDateTime now = LocalDateTime.now();
        long id= BaseContext.getCurrentId();

        //获取方法形参
        Object[] args = joinPoint.getArgs();
        if(args.length==0 ||args[0]==null){
            return;
        }
        Object entiy = args[0];
        //判断方法注解的数据库操作类型，来决定赋值
        if(annotation.value()== OperationType.INSERT){
            //添加操作，需要赋值4个变量
            //通过形参的反射原理来获取该类型的方法

            Method declaredMethod1 = entiy.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
            Method declaredMethod2 = entiy.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
            Method declaredMethod3 = entiy.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
            Method declaredMethod4 = entiy.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);


            declaredMethod1.invoke(entiy,now);
            declaredMethod2.invoke(entiy,id);
            declaredMethod3.invoke(entiy,now);
            declaredMethod4.invoke(entiy,id);

        }else if(annotation.value()==OperationType.UPDATE){
            Method declaredMethod3 = entiy.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
            Method declaredMethod4 = entiy.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
            declaredMethod3.invoke(entiy,now);
            declaredMethod4.invoke(entiy,id);
        }


    }
}
